﻿#include "NetClient.h"
#include <QNetworkReply>
#include <QUuid>
#include "../Debug.h"
#include "../Model/DataCenter.h"
#include "../Toast.h"
#include "file.qpb.h"
#include "friend.qpb.h"
#include "gateway.qpb.h"
#include "message_storage.qpb.h"
#include "message_transmit.qpb.h"
#include "notify.qpb.h"
#include "speech_recognition.qpb.h"
#include "user.qpb.h"
////////////////////////////////////////////
/// 用于发送 http请求和 websocket 数据传输的类
////////////////////////////////////////////
NetClient::NetClient(model::DataCenter* data_center)
    : data_center(data_center)
{
}

NetClient::~NetClient()
{
}

///// @brief 返回数据中心实例
// model::DataCenter* NetClient::get_data_center()
//{
//     return data_center;
// }

/// @brief 进行 http 测试操作, 服务端会返回一个 pong 消息
void NetClient::ping()
{
    LOG() << "Sending HTTP ping request to" << PING_URL.toString();
    QNetworkRequest request(PING_URL);
    QNetworkReply*  response = http_client.get(request);
    connect(response, &QNetworkReply::finished, this, [response]() {
        if (response->error() == QNetworkReply::NoError) {
            LOG() << "HTTP ping successful:" << QString(response->readAll());
        } else {
            LOG() << "HTTP ping failed:" << response->errorString();
            response->deleteLater();
        }
        response->deleteLater();
    });
}

/// @brief 初始化 WebSocket 客户端
bool NetClient::init_web_socket()
{
    /* 连接信号槽 */
    /* 建立连接 */
    connect(&ws_client, &QWebSocket::connected, this, [=]() {
        LOG() << "WebSocket connected";
        /* 发送身份认证 */
        // send_authentication();
    });

    /* 连接断开 */
    connect(&ws_client, &QWebSocket::disconnected, this, []() {
        LOG() << "WebSocket disconnected";
    });

    /* 收到文本消息 */
    connect(&ws_client, &QWebSocket::textMessageReceived, this, [this](const QString& message) {
        LOG() << "WebSocket message received:" << message;
    });

    /* 收到二进制消息 */
    connect(&ws_client, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray& message) {
        LOG() << "WebSocket binary message received";
        std::shared_ptr<chat::NotifyMessage> resp = std::make_shared<chat::NotifyMessage>();
        if (!resp->deserialize(&serializer, message)) {
            LOG() << "deserialize failed";
            return false;
        }
        this->handle_ws_binary_response(resp);
    });
    /* 建立连接 */
    ws_client.open(QUrl(WS_URL));
    return true;
}

/// @brief 处理 websocket 二进制消息
void NetClient::handle_ws_binary_response(std::shared_ptr<chat::NotifyMessage> response)
{
    using TYPE = chat::NotifyTypeGadget::NotifyType;
    switch (response->notifyType()) {
    case TYPE::CHAT_MESSAGE_NOTIFY: {
        // 将PB结构体转化为 model 中的结构体
        Message m_message;
        m_message.load(response->newMessageInfo().messageInfo());
        this->handle_ws_message(m_message);
        break;
    }
    case TYPE::CHAT_SESSION_CREATE_NOTIFY: {
        // 将PB结构体转化为 model 中的结构体
        ChatSession chat_session;
        chat_session.load(response->newChatSessionInfo().chatSessionInfo());
        this->handle_ws_creat_group(chat_session);
        break;
    }
    case TYPE::FRIEND_ADD_APPLY_NOTIFY: {
        // 将PB结构体转化为 model 中的结构体
        UserInfo user_info;
        user_info.load(response->friendAddApply().userInfo());
        this->handle_ws_add_friend(user_info);
        break;
    }
    case TYPE::FRIEND_ADD_PROCESS_NOTIFY: {
        // 将PB结构体转化为 model 中的结构体
        UserInfo user_info;
        user_info.load(response->friendProcessResult().userInfo());
        bool agree = response->friendProcessResult().agree();
        this->handle_ws_add_friend_process(user_info, agree);
        break;
    }
    case TYPE::FRIEND_REMOVE_NOTIFY: {
        // 将PB结构体转化为model中的结构体
        QString user_id = response->friendRemove().userId();
        this->handle_ws_remove_friend(user_id);
        break;
    }
    default:
        LOG() << "DEFAULT!!";
        break;
    }
}

/// @brief 当接收到消息时调用
void NetClient::handle_ws_message(const Message& message)
{
    QList<Message>* message_list = data_center->get_message_list(message.chat_session_id);
    if (message_list == nullptr) {
        /* 获取消息列表的实现方式是按需加载, 即点击这个会话时才加载,
         *  所以有可能这个会话ID对应的消息列表不存在,
         *  此时要通过网络获取, 注意这里要静默获取 */
        connect(data_center, &DataCenter::get_recent_messages_done_no_update_ui,
                data_center, &DataCenter::receive_message, Qt::UniqueConnection);
        data_center->get_recent_messages_async(message.chat_session_id, 50, false);
    } else {
        /* 这个会话列表存在, 直接向其后面添加元素 */
        message_list->append(message);
        data_center->receive_message(message.chat_session_id);
    }
}

/// @brief 通知收到删除好友
void NetClient::handle_ws_remove_friend(const QString& user_id)
{
    data_center->del_sepc_friend(user_id);
    emit data_center->del_friend_done();
}

/// @brief 通知收到好友申请
void NetClient::handle_ws_add_friend(const UserInfo& user_info)
{
    data_center->push_front_apply_list(user_info);
    emit data_center->receive_friend_apply();
}

/// @brief 通知收到了好友申请处理, 可能是被拒绝，也可能是被接受
void NetClient::handle_ws_add_friend_process(const UserInfo& user_info, bool agree)
{
    if (agree) {
        data_center->push_front_friend_list(user_info);
        emit data_center->receive_accept_friend_apply(user_info.nick_name);
    } else {
        emit data_center->receive_reject_friend_apply(user_info.nick_name);
    }
}

/// @brief 收到了加入新的群聊的申请
void NetClient::handle_ws_creat_group(const ChatSession& chat_session)
{
    /* 创建 chat_session_list */
    QList<ChatSession>* chat_session_list = data_center->get_chat_session_list();
    if (chat_session_list == nullptr) {
        LOG() << "chat_session_list is nullptr";
        return;
    }
    chat_session_list->push_front(chat_session);
    emit data_center->receive_create_group();
}

/// @brief 发送身份认证信息
void NetClient::send_authentication()
{
    if (!ws_client.isValid()) {
        LOG() << "WebSocket is not connected, cannot send authentication.";
        return;
    }
    chat::ClientAuthenticationReq req;
    req.setRequestId(make_id());
    req.setSessionId(data_center->get_login_session_id());
    QByteArray body = req.serialize(&serializer);
    ws_client.sendBinaryMessage(body);
    LOG() << "Sent authentication request with ID:" << req.requestId();
}

/// @brief 生成一个唯一的 RequestID
QString NetClient::make_id()
{
    return "S-" + QUuid::createUuid().toString().sliced(25, 12);
}

/// @brief 获取当前用户信息, DataCenter调用这个函数来获取当前用户信息
void NetClient::get_myself_info(const QString& login_session_id)
{
    /* 构建 body 并序列化 */
    chat::GetUserInfoReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_user_info request with request ID:" << request_body.requestId();
    // 构造HTTP请求并发送出去
    // QNetworkRequest request(GET_USER_INFO_URL);
    // request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-protobuf");
    // QNetworkReply*       response = http_client.post(request, body);
    // LOG() << "Sending GetUserInfo request with request ID:" << request_body.requestId();
    // 获取当前的响应
    // connect(response, &QNetworkReply::finished, this, [=] {
    //     /* 出错 */
    //     if(response->error() != QNetworkReply::NoError) {
    //         LOG() << "GetUserInfo request failed:" << response->errorString();
    //         response->deleteLater();
    //         return;
    //     }
    //     /* 拿到 body进行序列化 */
    //     QByteArray response_body = response->readAll();
    //     chat::GetUserInfoRsp* resp;
    //     resp->deserialize(&serializer, response_body);
    //     if (resp->success() != 0) {
    //         LOG() << "GetUserInfo request failed with error:" << resp->errmsg();
    //         response->deleteLater();
    //         return;
    //     }
    //     LOG() << "GetUserInfo response received, request ID:" << resp->requestId();
    // });
    /* ==========================使用函数封装简化一下上面的调用流程================================ */
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_USER_INFO_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto user_info_resp = handle_http_response<chat::GetUserInfoRsp>(response);
        if (user_info_resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_cur_user_info(user_info_resp);
        /* 发送信号 */
        emit data_center->get_myself_info_done();
    });
}
/// @brief 获取好友列表, DataCenter调用这个函数来获取好友列表
void NetClient::get_friend_list(const QString& login_session_id)
{
    /* 构建 body 并序列化 */
    chat::GetFriendListReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_friend_list request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_FRIEND_LIST_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto frend_list_resp = handle_http_response<chat::GetFriendListRsp>(response);
        if (frend_list_resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_friend_list(frend_list_resp);
        emit data_center->get_friend_list_done();  // 收到数据了再发送信号
    });
}


/// @brief 获取会话列表, DataCenter调用这个函数来获取会话列表
void NetClient::get_chat_session_list(const QString& login_session_id)
{
    /* 构建 body 并序列化 */
    chat::GetFriendListReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_chat_session_list request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_SESSION_LIST_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto frend_list_resp = handle_http_response<chat::GetChatSessionListRsp>(response);
        if (frend_list_resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_chat_session_list(frend_list_resp);
        emit data_center->get_chat_session_list_done();  // 收到数据了再发送信号
    });
}

/// @brief 获取好友申请列表, DataCenter调用这个函数来获取好友申请列表
void NetClient::get_friend_apply_list(const QString& login_seesion_id)
{
    /* 构建 body 并序列化 */
    chat::GetPendingFriendEventListReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_seesion_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_friend_apply_list request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_FRIEND_APPLY_LIST_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto frend_list_resp = handle_http_response<chat::GetPendingFriendEventListRsp>(response);
        if (frend_list_resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_friend_apply_list(frend_list_resp);
        emit data_center->get_friend_apply_list_done();  // 收到数据了再发送信号
    });
}

/// @brief 获取指定会话ID对应的消息
void NetClient::get_recent_messages(const QString& login_session_id, const QString& chat_session_id, int cnt, bool update_ui)
{
    /* 构建 body 并序列化 */
    chat::GetRecentMsgReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setChatSessionId(chat_session_id);
    request_body.setMsgCount(cnt);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_recent_messages request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_RECENT_MSG_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto recent_msgs = handle_http_response<chat::GetRecentMsgRsp>(response);
        if (recent_msgs == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_recent_messages(chat_session_id, recent_msgs);
        if (update_ui) {
            emit data_center->get_recent_messages_done(chat_session_id);  // 收到数据了再发送信号
        } else {
            emit data_center->get_recent_messages_done_no_update_ui(chat_session_id);
        }
    });
}

/// @brief 发送消息, DataCenter调用这个函数来发送消息
///        支持发送多种类型的的消息, 具体类型由 MessageType 来指定
/// @param extra_info: 额外的信息, 例如文件名称
void NetClient::send_message(const QString& login_session_id, const QString& chat_session_id,
                             MessageType type, const QByteArray& content, const QString& extra_info)
{
    /* 构建 body 并序列化 */
    chat::NewMessageReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setChatSessionId(chat_session_id);
    chat::MessageContent message;
    using M_TYPE = chat::MessageTypeGadget::MessageType;
    switch (type) {
    case model::TEXT_TYPE: {
        chat::StringMessageInfo string_message;
        message.setMessageType(M_TYPE::STRING);
        string_message.setContent(content);
        message.setStringMessage(string_message);
        break;
    }
    case model::IMAGE_TYPE: {
        chat::ImageMessageInfo image_message;
        message.setMessageType(M_TYPE::IMAGE);
        image_message.setFileId("");  // 客户端不需要设置
        image_message.setImageContent(content);
        message.setImageMessage(image_message);
        break;
    }
    case model::SPEECH_TYPE: {
        chat::SpeechMessageInfo speech_message;
        message.setMessageType(M_TYPE::SPEECH);
        speech_message.setFileId("");
        speech_message.setFileContents(content);
        message.setSpeechMessage(speech_message);
        break;
    }
    case model::FILE_TYPE: {
        chat::FileMessageInfo file_message;
        message.setMessageType(M_TYPE::FILE);
        file_message.setFileId("");
        file_message.setFileContents(content);
        file_message.setFileName(extra_info);
        file_message.setFileSize(content.size());
        message.setFileMessage(file_message);
        break;
    }
    case model::UNKNOW:
        LOG() << "Wrong Type: " << type;
        break;
    default:
        LOG() << "DEFAULT!!!!";
        break;
    }
    request_body.setMessage(message);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending send_message request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SEND_MSG_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto send_msg = handle_http_response<chat::NewMessageRsp>(response);
        if (send_msg == nullptr) {
            return;
        }
        /* 发送信号 */
        emit data_center->send_message_done(type, content, extra_info);  // 收到数据了再发送信号
    });
}

/// @brief 发送设置用户的昵称请求
void NetClient::set_user_nick_name(const QString& login_session_id, const QString& nick_name)
{
    /* 构建 body 并序列化 */
    chat::SetUserNicknameReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setNickname(nick_name);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending set_user_nick_name request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SET_NICK_NAME_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::SetUserNicknameRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_cur_user_info_nick_name(nick_name);
    });
}

/// @brief 发送设置用户的个性签名请求
void NetClient::set_user_description(const QString& login_session_id, const QString& desc)
{
    /* 构建 body 并序列化 */
    chat::SetUserDescriptionReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setDescription(desc);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending set_user_description request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SET_DESCRIPTION_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::SetUserDescriptionRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_cur_user_info_desc(desc);
    });
}

/// @brief 发送重新设置用户的手机号码请求
void NetClient::set_user_phone_num(const QString& login_session_id, const QString& phone_num, const QString& phone_verify_code_id, const QString& phone_verify_code)
{
    /* 构建 body 并序列化 */
    chat::SetUserPhoneNumberReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setPhoneNumber(phone_num);
    request_body.setPhoneVerifyCodeId(phone_verify_code_id);
    request_body.setPhoneVerifyCode(phone_verify_code);
    /* 构建 body 并序列化 */
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending set_user_phone_num request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SET_PHONE_NUM_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::SetUserPhoneNumberRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_cur_user_info_phone_num(phone_num);
    });
}

/// @brief 发送获取手机验证码请求
void NetClient::get_phone_verify_code(const QString& phone_num)
{
    /* 构建 body 并序列化 */
    chat::PhoneVerifyCodeReq request_body;
    request_body.setRequestId(make_id());
    request_body.setPhoneNumber(phone_num);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_phone_verify_code request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_PHONE_VERIFY_CODE_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::PhoneVerifyCodeRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_phone_verify_code_id(resp);
        emit data_center->get_phone_verify_code_done();
    });
}

/// @brief 发送设置用户头像请求
void NetClient::set_user_avatar(const QString& login_session_id, const QByteArray& image)
{
    /* 构建 body 并序列化 */
    chat::SetUserAvatarReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setAvatar(image);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending set_user_avatar request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SET_AVATAR_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::SetUserAvatarRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->set_cur_user_info_avatar(image);
        emit data_center->set_cur_user_info_avatar_done();  // 发送信号用于更新UI, 主要是MainWiget中使用
    });
}

/// @brief 发送删除好友请求
void NetClient::del_friend(const QString& login_session_id, const QString& user_id)
{
    /* 构建 body 并序列化 */
    chat::FriendRemoveReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setPeerId(user_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending del_friend request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(DEL_FRIEND_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::FriendRemoveRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        data_center->del_sepc_friend(user_id);
        emit data_center->del_friend_done();
    });
}

/// @brief 发送添加好友请求
void NetClient::add_friend(const QString& login_session_id, const QString& user_id)
{
    /* 构建 body 并序列化 */
    chat::FriendAddReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setRespondentId(user_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending add_friend request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(ADD_FRIEND_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::FriendAddRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        emit data_center->add_friend_done();
    });
}

/// @brief 发送接收好友申请的请求
void NetClient::accept_friend_apply(const QString& login_session_id, const QString& user_id)
{
    /* 构建 body 并序列化 */
    chat::FriendAddProcessReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setNotifyEventId("");
    request_body.setUserId("");
    request_body.setAgree(true);
    request_body.setApplyUserId(user_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending accept_friend_apply request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(PROCESS_FRIEND_APPLY_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::FriendAddProcessRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        UserInfo user_info = data_center->remove_from_apply_list(user_id);
        data_center->push_front_friend_list(user_info);
        emit data_center->accept_friend_apply_done(user_info.nick_name);
    });
}

/// @brief 发送拒绝好友申请的请求
void NetClient::reject_friend_apply(const QString& login_session_id, const QString& user_id)
{
    /* 构建 body 并序列化 */
    chat::FriendAddProcessReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setNotifyEventId("");
    request_body.setUserId("");
    request_body.setAgree(false);
    request_body.setApplyUserId(user_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending reject_friend_apply request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(PROCESS_FRIEND_APPLY_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::FriendAddProcessRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据 */
        UserInfo user_info = data_center->remove_from_apply_list(user_id);
        emit     data_center->reject_friend_apply_done(user_info.nick_name);
    });
}

/// @brief 根据选中的用户id, 创建群聊
void NetClient::create_group(const QString& login_session_id, const QList<QString>& user_ids)
{
    /* 构建 body 并序列化 */
    chat::ChatSessionCreateReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setChatSessionName("It's My Go!!!!!");
    request_body.setMemberIdList(user_ids);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending create_group request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(CREATE_GROUP_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::ChatSessionCreateRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据, 这里不需要设置数据, 而是通过WS发送全体消息 */
        emit data_center->creat_group_done();
    });
}

/// @brief 获取指定ID的群成员列表
void NetClient::get_group_member_list(const QString& login_session_id, const QString& chat_session_id)
{
    /* 构建 body 并序列化 */
    chat::GetChatSessionMemberReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setChatSessionId(chat_session_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_group_member_list request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_GROUP_MEMBER_LIST_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::GetChatSessionMemberRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据, 发送信号 */
        data_center->add_group_member_list(chat_session_id, resp);
        emit data_center->get_group_member_list_done();
    });
}

/// @brief 根据关键字搜索用户
void NetClient::search_user(const QString& login_session_id, const QString& search_key)
{
    /* 构建 body 并序列化 */
    chat::FriendSearchReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setSearchKey(search_key);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending search_user request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SEARCH_USER_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::FriendSearchRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据, 发送信号 */
        data_center->set_search_user_result(resp);
        emit data_center->search_user_done();
    });
}

/// @brief 获取指定会话id, 指定key的群消息, 根据关键字获取
void NetClient::search_history_message(const QString& login_session_id, const QString& chat_session_id, const QString& search_key)
{
    /* 构建 body 并序列化 */
    chat::MsgSearchReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setChatSessionId(chat_session_id);
    request_body.setSearchKey(search_key);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending search_history_message request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SEARCH_HISTORY_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::MsgSearchRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据, 发送信号 */
        data_center->set_search_history_msg(resp->msgList());
        emit data_center->search_history_message_done();
    });
}

/// @brief 异步获取指定会话id的群消息, 根据时间获取
void NetClient::search_history_message_by_time(const QString& login_session_id, const QString& chat_session_id, qint64 start_time, qint64 end_time)
{
    /* 构建 body 并序列化 */
    chat::GetHistoryMsgReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setChatSessionId(chat_session_id);
    request_body.setStartTime(start_time);
    request_body.setOverTime(end_time);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending search_history_message_by_time request with request ID:" << request_body.requestId();
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SEARCH_HISTORY_URL_BY_TIME, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::GetHistoryMsgRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 设置数据, 发送信号 */
        data_center->set_search_history_msg(resp->msgList());
        emit data_center->search_history_message_done();
    });
}

/// @brief 发送用户名登录请求
void NetClient::user_login(const QString& user_name, const QString& pwd)
{
    /* 构建 body 并序列化 */
    chat::UserLoginReq request_body;
    request_body.setRequestId(make_id());
    request_body.setNickname(user_name);
    request_body.setPassword(pwd);
    request_body.setVerifyCode("");  // 这两条不需要设置, 已经在客户端处理完了
    request_body.setVerifyCodeId("");
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending user_login request with request ID:" << request_body.requestId()
          << " user_name" << user_name << " pwd: " << pwd;
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(USER_LOGIN_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        bool    is_ok  = true;
        QString reason = "";
        auto    resp   = handle_http_response<chat::UserLoginRsp>(response, &is_ok, &reason);
        if (resp == nullptr) {
            emit data_center->user_login_done(is_ok, reason);
            return;
        }
        /* 设置数据, 发送信号 */
        data_center->set_login_session_id(resp->loginSessionId());
        emit data_center->user_login_done(is_ok, reason);
    });
}

/// @brief 发送用户名注册请求
void NetClient::user_register(const QString& user_name, const QString& pwd)
{
    /* 构建 body 并序列化 */
    chat::UserRegisterReq request_body;
    request_body.setRequestId(make_id());
    request_body.setNickname(user_name);
    request_body.setPassword(pwd);
    request_body.setVerifyCode("");  // 这两条不需要设置, 已经在客户端处理完了
    request_body.setVerifyCodeId("");
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending user_register request with request ID:" << request_body.requestId()
          << " user_name" << user_name << " pwd: " << pwd;
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(USER_REGISTER_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        bool    is_ok  = true;
        QString reason = "";
        auto    resp   = handle_http_response<chat::UserRegisterRsp>(response, &is_ok, &reason);
        if (resp == nullptr) {
            emit data_center->user_register_done(is_ok, reason);
            return;
        }
        /* 发送信号 */
        emit data_center->user_register_done(is_ok, reason);
    });
}

/// @brief 使用手机号码登录
void NetClient::phone_login(const QString& phone_num, const QString& verify_code)
{
    QString verify_code_id = data_center->get_phone_verify_code_id();
    if (verify_code_id == "") {
        LOG() << "Invalid code id!";
        return;
    }
    /* 构建 body 并序列化 */
    chat::PhoneLoginReq request_body;
    request_body.setRequestId(make_id());
    request_body.setPhoneNumber(phone_num);
    request_body.setVerifyCode(verify_code);
    request_body.setVerifyCode(verify_code_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending phone_login request with request ID:" << request_body.requestId()
          << " phone_num:" << phone_num << " verify_code:" << verify_code;
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(PHONE_LOGIN_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        bool    is_ok  = true;
        QString reason = "";
        auto    resp   = handle_http_response<chat::PhoneLoginRsp>(response, &is_ok, &reason);
        if (resp == nullptr) {
            emit data_center->phone_login_done(is_ok, reason);
            return;
        }
        /* 设置数据, 发送信号 */
        data_center->set_login_session_id(resp->loginSessionId());
        emit data_center->phone_login_done(is_ok, reason);
    });
}

/// @brief 使用手机号码注册
void NetClient::phone_register(const QString& phone_num, const QString& verify_code)
{
    QString verify_code_id = data_center->get_phone_verify_code_id();
    if (verify_code_id == "") {
        LOG() << "Invalid code id!";
        return;
    }
    /* 构建 body 并序列化 */
    chat::PhoneRegisterReq request_body;
    request_body.setRequestId(make_id());
    request_body.setPhoneNumber(phone_num);
    request_body.setVerifyCode(verify_code);
    request_body.setVerifyCode(verify_code_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending phone_register request with request ID:" << request_body.requestId()
          << " phone_num:" << phone_num << " verify_code:" << verify_code;
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(PHONE_REGISTER_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        bool    is_ok  = true;
        QString reason = "";
        auto    resp   = handle_http_response<chat::PhoneRegisterRsp>(response, &is_ok, &reason);
        if (resp == nullptr) {
            emit data_center->phone_register_done(is_ok, reason);
            return;
        }
        /* 发送信号 */
        emit data_center->phone_register_done(is_ok, reason);
    });
}

/// @brief 获取单个文件的内容
void NetClient::get_single_file(const QString& login_session_id, const QString& file_id)
{
    /* 构建 body 并序列化 */
    chat::GetSingleFileReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setFileId(file_id);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending get_single_file request with request ID:" << request_body.requestId()
          << " login_session_id:" << login_session_id << " file_id:" << file_id;
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(GET_SINGLE_FILE_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        auto resp = handle_http_response<chat::GetSingleFileRsp>(response);
        if (resp == nullptr) {
            return;
        }
        /* 发送信号 */
        emit data_center->get_single_file_done(file_id, resp->fileData().fileContent());
    });
}

/// @brief 进行语音识别
void NetClient::speech_recognition(const QString& login_session_id, const QByteArray& data)
{
    /* 构建 body 并序列化 */
    chat::SpeechRecognitionReq request_body;
    request_body.setRequestId(make_id());
    request_body.setSessionId(login_session_id);
    request_body.setUserId("");
    request_body.setSpeechContent(data);
    QByteArray body = request_body.serialize(&serializer);
    LOG() << "Sending speech_recognition request with request ID:" << request_body.requestId()
          << " login_session_id:" << login_session_id;
    /* 构造HTTP请求并发送出去 */
    auto response = send_http_request(SPEECH_RECOGNITION_URL, body);
    /* 处理当前的响应 */
    connect(response, &QNetworkReply::finished, this, [=] {
        /* 解析响应 */
        bool    ok     = false;
        QString reason = "";
        auto    resp   = handle_http_response<chat::SpeechRecognitionRsp>(response, &ok, &reason);
        /* 发送信号 */
        emit data_center->speech_recognition_done(ok, reason, resp->recognitionResult());
    });
}

/// @brief 发送 HTTP 请求
QNetworkReply* NetClient::send_http_request(const QUrl& url, const QByteArray& body)
{
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-protobuf");
    QNetworkReply* response = http_client.post(request, body);
    return response;
}
